package homework0606;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
/**
 * 作业: 自己实现 java.lang.Collection 接口中除了 iterator 和  toArray(T[] a) 之外的其它方法
 */
public class Container implements Collection<Object>{

    private Object[] elements; //声明一个数组类型的引用变量
    //声明一个 int 类型的变量用来统计容器中的元素个数
    private int counter;
    // 定义表示 默认加载因子 的 常量
    private static final float loadFactor = 0.75F;
    // 定义表示 容器最大容量 的 常量
    private static final int MAXIMUM_CAPACITY = 1 << 30;

    public Container(){
        this(10 , 0.75F);
    }
    public Container(int initialCapacity , float loadFactor){
        if ( initialCapacity <= 0 ){
            initialCapacity = 10;
        }
        this.elements = new Object[ initialCapacity ];
    }

    public void ensureCapacity(){
        if ( counter > elements.length * loadFactor){
            // 将 原来的数组 的地址 暂存到 temp 变量中
            final Object[] temp = this.elements;
            // 扩容方式就是在原来基础上增长约 1.5 倍
            int newLength = temp.length * 3 / 2 + 1 ;
            if( newLength > MAXIMUM_CAPACITY ) {
                RuntimeException x = new RuntimeException( "容器容量超过最大值" );
                throw x ; // 抛出异常实例导致整个方法立即结束
            }
            // 创建新数组 ( 创建一个新的、更大的数组 ) 并将新数组地址赋值到 elements 变量
            this.elements = new Object[ newLength ];
            // 将原数组中的[ 0 , counter ) 之间的元素拷贝到新数组中
            System.arraycopy(temp, 0, elements, 0, counter);
            // 后续就使用新数组 (放弃老数组) 了 ( 因为 elements 变量中存储了 新数组的地址 )
        }
    }

    @Override
    public int size() {
        return this.counter;
    }

    @Override
    public boolean isEmpty() {
        return counter == 0 ;
    }

    @Override
    public boolean contains(Object o) {
//        for ( int i = 0 , n = elements.length ; i < n ; i++ )
//        {
//            if ( elements[i] == o ){
//                return true;
//            }
//        }//这种方法判断 字符 时候是错误的
       for ( int i = 0 ; i < counter ; i++ )
       {
           if ( elements[i] .equals(o) ){
                return true;
            }
        }
        //return elements.indexOf( o ) != -1;
        return false;
    }

    @Override
    public Object[] toArray() {
        // 将 elements 数组中的 [ 0 , counter ) 之间的元素复制到新数组
        Object[] array = Arrays.copyOf(elements, counter );
        return array;
    }

    @Override
    public boolean add(Object e) {
        this.ensureCapacity();
        elements[counter] = e;
        counter++;
        return true;
    }

    @Override
    public boolean remove(Object o) {
        //获取要删除元素的 索引
        int index = indexOf( o );
        if( index != -1 ) {
            // 统计需要拷贝的元素个数
            int n = counter - 1 - index ;
            // 将 elements 的 [ index + 1 , counter ) 之间的元素 拷贝 到 elements 的 [ index , counter - 1 ) 之间
            System.arraycopy( elements, index + 1 ,  elements , index , n );//【注意这行代码】
            // 因为删除了一个元素，所以 counter 需要减去 1
            counter-- ;
            return true ;// 成功删除后返回 true
        }
        return false ; // 如果未对容器造成任何影响则返回 false
    }

    /**
     * 寻找指定元素在容器中的首次出现的位置并返回其索引
     * @param o 被寻找的元素
     * @return 返回被寻找元素在容器中的位置(索引)
     */
    public int indexOf( Object o ) {
        for( int i = 0 ; i < counter ; i++ ) {
            // 从数组中获取下标i处的元素
            Object e = elements[ i ];
            if( e == o || ( e != null && e.equals( o ) ) ) {
                return i ;  // 当找到指定元素时就返回相应的索引
            }
        }
        return -1 ; // 如果未找到相应的元素则返回 -1
    }

    @Override
    public void clear() {
        this.counter = 0 ;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        for (Object e : c.toArray()) {
            if (!contains(e)) // Invokes safe contains() above
                return false;
        }
        return true;
    }

    @Override
    public boolean addAll(Collection<? extends Object> c) {
        Object[] al = c.toArray();
        for( Object x : al )
        {
            this.ensureCapacity();
            elements[counter++] = x ;
        }
        return true;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        Object[] ra = c.toArray();
        for ( Object x : ra){
            int index = indexOf( x );
            if ( index != -1 ){
                // 统计需要拷贝的元素个数
                int n = counter - 1 - index ;
                // 将 elements 的 [ index + 1 , counter ) 之间的元素 拷贝 到 elements 的 [ index , counter - 1 ) 之间
                System.arraycopy( elements, index + 1 ,  elements , index , n );//【注意这行代码】
                // 因为删除了一个元素，所以 counter 需要减去 1
                counter-- ;
            }
        }
        return true;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
//        int n = 1;
//        Object[] temp = new Object[ n ];
//        Object[] array = c.toArray();
//        for ( Object x : c.toArray() ){
//            System.out.println( contains( x ));
//        }
        Object[] ra = c.toArray();
        int num = 0;
        for ( Object x : ra){
            int index = indexOf( x );
            if ( index != -1 ){
                elements[num] = x;
                num++;
            }
        }
        counter = num;
        return true;
    }

    @Override
    public Iterator<Object> iterator() { // 【不去实现】
        return null;
    }


    @Override
    public <T> T[] toArray(T[] a) { // 【不去实现】
        return null;
    }

    @Override
    public String toString(){
        StringBuilder builder = new StringBuilder();
        builder.append("~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ");
        builder.append('\n');
        builder.append("容器的当前容量是 : " + elements.length);
        builder.append('\n');
        builder.append( "容器的元素个数是: " + counter );
        builder.append( "\n" );

        if( counter > 0 ) {
            builder.append( "容器中的元素有: " );
            for( int i = 0 ; i < counter ; i++ ) {
                builder.append( elements[ i ] );
                builder.append( i < counter -1 ? " , " : "\n" );
            }
        } else {
            builder.append( "容器中尚未添加有效元素" );
            builder.append( "\n" );
        }

        builder.append("~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ");
        String s = builder.toString();
        return s;
    }

}
